package com.huangfu.learning.javabase.java.pattern.action.iterator;

/**
 * Created with IntelliJ IDEA.
 * Author: huangfu.daohui
 * Date: 2018/8/11
 * Time: 13:57
 * Version: 1.0
 * Description:迭代器模式：顺序访问集合对象的元素，不需要知道集合对象的底层表示。
 * 参考：https://blog.csdn.net/hudashi/article/details/50982568
 * https://blog.csdn.net/jason0539/article/details/45070441
 * <p>
 * 关键代码：定义接口：hasNext, next。
 * 优点： 1、它支持以不同的方式遍历一个聚合对象。
 * 2、迭代器简化了聚合类。
 * 3、在同一个聚合上可以有多个遍历。
 * 4、在迭代器模式中，增加新的聚合类和迭代器类都很方便，无须修改原有代码。
 * <p>
 * 缺点：由于迭代器模式将存储数据和遍历数据的职责分离，增加新的聚合类需要对应增加新的迭代器类，类的个数成对增加，这在一定程度上增加了系统的复杂性。
 * <p>
 * 使用场景： 1、访问一个聚合对象的内容而无须暴露它的内部表示。
 * 2、需要为聚合对象提供多种遍历方式。
 * 3、为遍历不同的聚合结构提供一个统一的接口。
 * <p>
 * 角色
 * 抽象迭代子(Iterator)角色：此抽象角色定义出遍历元素所需的接口。
 * 具体迭代子(ConcreteIterator)角色：此角色实现了Iterator接口，并保持迭代过程中的游标位置。
 * 聚集(Aggregate)角色：此抽象角色给出创建迭代子(Iterator)对象的接口。
 * 具体聚集(ConcreteAggregate)角色：实现了创建迭代子(Iterator)对象的接口，返回一个合适的具体迭代子实例。
 * 客户端(Client)角色：持有对聚集及其迭代子对象的引用，调用迭代子对象的迭代接口，也有可能通过迭代子操作聚集元素的增加和删除
 **/
public class IteratorPattern {

    // 客户端类 测试
    public static void main(String[] args) {
        Object[] objArray = {"One", "Two", "Three", "Four", "Five", "Six"};
        //创建聚合对象
        Aggregate agg = new ConcreteAggregate(objArray);
        //循环输出聚合对象中的值
        Iterator it = agg.createIterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

    }
}

/**
 * 抽象迭代子(Iterator)角色
 */
interface Iterator {

    // 前一个
    Object previous();

    // 下一个
    Object next();

    // 是否有下一个
    boolean hasNext();

    // 第一个
    Object first();

}

/**
 * 聚集(Aggregate)角色
 */
interface Aggregate {

    //工厂方法，创建相应迭代子对象的接口
    Iterator createIterator();

    // 取得集合元素
    Object get(int i);

    // 取得集合的大小
    int size();
}

/**
 * 具体迭代子(ConcreteIterator)角色
 */
class ConcreteIterator implements Iterator {

    private ConcreteAggregate aggregate;
    private int pos = -1;

    public ConcreteIterator(ConcreteAggregate aggregate) {
        this.aggregate = aggregate;
    }

    @Override
    public Object previous() {
        if (pos > 0) {
            pos--;
        }
        return aggregate.get(pos);
    }

    @Override
    public Object next() {
        if (pos < aggregate.size() - 1) {
            pos++;
        }
        return aggregate.get(pos);
    }

    @Override
    public boolean hasNext() {
        if (pos < aggregate.size() - 1) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Object first() {
        pos = 0;
        return aggregate.get(pos);
    }
}

/**
 * 具体聚集(ConcreteAggregate)角色
 */
class ConcreteAggregate implements Aggregate {

    private Object[] objArray = null;

    /**
     * 构造方法，传入聚合对象的具体内容
     */
    public ConcreteAggregate(Object[] objArray) {
        this.objArray = objArray;
    }

    ////创建聚合对象
    @Override
    public Iterator createIterator() {
        return new ConcreteIterator(ConcreteAggregate.this);
    }


    @Override
    public Object get(int i) {
        return objArray[i];
    }

    @Override
    public int size() {
        return objArray.length;
    }
}